package com.chenc.unitdemo.jwt.service.impl;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.InvalidClaimException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.chenc.unitdemo.jwt.dto.UserLoginDto;
import com.chenc.unitdemo.jwt.golbal.BusinessException;
import com.chenc.unitdemo.jwt.service.JWTService;
import com.chenc.unitdemo.normal.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.util.Calendar;

import static com.chenc.unitdemo.normal.redisKey.RedisKey.LOGIN_REDIS_MAP;

/**
 * @ClassName
 * @Describtion:
 * @Author:Chenc
 * @Date:2024/1/8 14:57
 * @Version 1.0
 */
@Service
@Slf4j
public class JWTServiceImpl implements JWTService {


    @Autowired
    RedisService redisService;
    private final Integer deadTime = 12;
    private final String prefixStr = "$$22%%1.&&Aa999~";

    @Override
    public UserLoginDto createToken(UserLoginDto userLoginDto) {
        String salt = prefixStr ;//userLoginDto.getPassword()
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MINUTE, deadTime);
        String token = JWT.create()
                .withClaim("userId", userLoginDto.getUserId())
                .withClaim("username", userLoginDto.getUsername())
                .withClaim("nickname", userLoginDto.getNickname())
                .withExpiresAt(calendar.getTime())
                .sign(Algorithm.HMAC256(salt));
        userLoginDto.setToken(token);
        return userLoginDto;
    }

    @Override
    public Boolean createTokenAndSendRedis(UserLoginDto userLoginDto) {
        return redisService.hSet(LOGIN_REDIS_MAP,userLoginDto.getUserId(),userLoginDto.getToken(), 1000 * deadTime);
    }

    @Override
    public UserLoginDto verfyTokenAndcheckRedisToken(String token){
        try{
            UserLoginDto userLoginDto = verfyToken(token,prefixStr);
            Object o = redisService.hGet(LOGIN_REDIS_MAP, userLoginDto.getUserId());
            if (null!= o ){
                String redisToken = String.valueOf(o);
                if (token.equals(redisToken)){
                    return userLoginDto;
                }
            }
            return null;
        }catch(AlgorithmMismatchException algorithmMismatchException){
            log.info("verfyToken#algorithmMismatchException ");
            throw new BusinessException("登录密码错误，请重新登录");
        }catch(SignatureVerificationException signatureVerificationException){
            log.info("verfyToken#signatureVerificationException ");
            throw new BusinessException("登录密码错误，请重新登录");
        }catch(TokenExpiredException tokenExpiredException){
            log.info("verfyToken#tokenExpiredException ");
            throw new BusinessException("登录超时，请重新登录");
        }catch(InvalidClaimException invalidClaimException){
            log.info("verfyToken#invalidClaimException ");
            throw new BusinessException("登录密码错误，请重新登录");
        }catch(Exception e){
            log.info("verfyToken#Exception");
        }
        return null;

    }

    @Override
    public UserLoginDto verfyToken(String token,String salt) {
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(salt)).build();
        DecodedJWT verify = jwtVerifier.verify(token);
        String userId = verify.getClaim("userId").asString();
        String username = verify.getClaim("username").asString();
        String nickname = verify.getClaim("nickname").asString();
        UserLoginDto userLoginDto = UserLoginDto.builder()
                .userId(userId)
                .username(username)
                .nickname(nickname).build();
        return userLoginDto;
    }

}
